﻿using System;
using System.Linq;
using System.Xml.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using QXGameEngine.Interface;
using QXGameEngine.Logic;
using System.Windows.Media.Imaging;

namespace QXGameEngine.Control {

    public partial class QXSprite : UserControl ,IObject {

        /// <summary>
        /// 精灵控件
        /// </summary>
        public QXSprite() {
            InitializeComponent();
            Timer = new DispatcherTimer();
            Timer.Interval = TimeSpan.FromMilliseconds(400);
            Timer.Tick += new EventHandler(Timer_Tick);
            Timer.Start();
        }

        /// <summary>
        /// 获取或设置内置计时器
        /// </summary>
        public DispatcherTimer Timer { get; set; }

        /// <summary>
        /// 获取或设置根画布容器
        /// </summary>
        public Canvas RootCanvas {
            get { return this.Container; }
        }

        /// <summary>
        /// 获取父容器
        /// </summary>
        public Canvas ParentCanvas {
            get { return this.Parent as Canvas; }
        }

        #region 身份属性

        /// <summary>
        /// 获取或设置头像代号
        /// </summary>
        public int FaceSign { get; set; }

        /// <summary>
        /// 获取或设置PK模式
        /// </summary>
        public PKModes PKMode { get; set; }

        /// <summary>
        /// 获取或设置门派名
        /// </summary>
        public string VFaction {
            get { return Faction.Text; }
            set { Faction.Text = value; }
        }

        /// <summary>
        /// 获取或设置家族名
        /// </summary>
        public string VClan {
            get { return Clan.Text; }
            set { Clan.Text = value; }
        }

        /// <summary>
        /// 获取或设置姓名
        /// </summary>
        public string VSName {
            get { return SName.Text; }
            set { SName.Text = value; }
        }

        #endregion

        #region 基本值属性

        double[] _AdditionalEffect = new double[6];
        /// <summary>
        /// 获取或设置被附加属性对应伤害效果
        /// </summary>
        public double[] AdditionalEffect {
            get { return _AdditionalEffect; }
            set { _AdditionalEffect = value; }
        }

        double[] _AdditionalEffectTime = new double[6];
        /// <summary>
        /// 获取或设置被附加属性对应持续时间
        /// </summary>
        public double[] AdditionalEffectTime {
            get { return _AdditionalEffectTime; }
            set { _AdditionalEffectTime = value; }
        }

        /// <summary>
        /// 获取或设置对该精灵给予持续性魔法伤害的对象精灵名
        /// </summary>
        public string AdditionalEffectSprite{ get; set; }

        /// <summary>
        /// 获取或设置等级
        /// </summary>
        public int VLevel { get; set; }

        /// <summary>
        /// 获取或设置自身的经验值(如果为怪物等NPC,则为杀它的玩家可以得到的经验值)
        /// </summary>
        public int VExperience { get; set; }

        /// <summary>
        /// PK值(正值代表善良,负值代表邪恶, 正负7之间)
        /// </summary>
        public int VPK { get; set; }

        /// <summary>
        /// 获取最大负重
        /// </summary>
        public double VBurdenMax {
            get { return ABase[0] + Equip[0] + Buff[0] + VPower * Coefficient[0]; }
        }

        /// <summary>
        /// 获取物理攻击力最小值
        /// </summary>
        public double VAttackMin {
            get { return ABase[1] + Equip[1] + Buff[1] + VPower * Coefficient[1]; }
        }

        /// <summary>
        /// 获取物理攻击力最大值
        /// </summary>
        public double VAttackMax {
            get { return ABase[2] + Equip[2] + Buff[2] + VPower * Coefficient[2]; }
        }

        /// <summary>
        /// 获取命中值
        /// </summary>
        public double VHit {
            get { return ABase[3] + Equip[3] + Buff[3] + VAgile * Coefficient[3]; }
        }

        /// <summary>
        /// 获取闪避值
        /// </summary>
        public double VDodge {
            get { return ABase[4] + Equip[4] + Buff[4] + VAgile * Coefficient[4]; }
        }

        /// <summary>
        /// 获取跑步速度(每移动一个单元格的花费时间,越小越快)
        /// </summary>
        public double VRunSpeed {
            get { return ABase[5] + Equip[5] + Buff[5] - VAgile * Coefficient[5]; }
        }

        /// <summary>
        /// 获取物攻速度(越小越快)
        /// </summary>
        public double VAttackSpeed {
            get { return ABase[6] + Equip[6] + Buff[6] - VAgile * Coefficient[6]; }
        }

        /// <summary>
        /// 获取施法速度(越小越快)
        /// </summary>
        public double VMagicSpeed {
            get { return ABase[7] + Equip[7] + Buff[7] - VAgile * Coefficient[7]; }
        }

        /// <summary>
        /// 获取或设置当前生命值
        /// </summary>
        public double VLife { get; set; }

        /// <summary>
        /// 获取最大生命值
        /// </summary>
        public double VLifeMax {
            get { return ABase[8] + Equip[8] + Buff[8] + VPhysique * Coefficient[8]; }
        }

        /// <summary>
        /// 获取物理防御力
        /// </summary>
        public double VDefense {
            get { return ABase[9] + Equip[9] + Buff[9] + VPhysique * Coefficient[9]; }
        }

        /// <summary>
        /// 获取格档率
        /// </summary>
        public double VBlock {
            get { return ABase[10] + Equip[10] + Buff[10] + VPhysique * Coefficient[10]; }
        }

        /// <summary>
        /// 获取或设置当前魔法值
        /// </summary>
        public double VMana { get; set; }

        /// <summary>
        /// 获取最大魔法值
        /// </summary>
        public double VManaMax {
            get { return ABase[11] + Equip[11] + Buff[11] + VWisdom * Coefficient[11]; }
        }

        /// <summary>
        /// 获取魔法防御力
        /// </summary>
        public double VMagicDefense {
            get { return ABase[12] + Equip[12] + Buff[12] + VWisdom * Coefficient[12]; }
        }

        /// <summary>
        /// 获取魔法攻击力最小值
        /// </summary>
        public double VMagicMin {
            get { return ABase[13] + Equip[13] + Buff[13] + VWisdom * Coefficient[13]; }
        }

        /// <summary>
        /// 获取魔法攻击力最大值
        /// </summary>
        public double VMagicMax {
            get { return ABase[14] + Equip[14] + Buff[14] + VWisdom * Coefficient[14]; }
        }

        /// <summary>
        /// 获取暴击率
        /// </summary>
        public double VBurst {
            get { return ABase[15] + Equip[15] + Buff[15] + VLucky * Coefficient[15]; }
        }

        /// <summary>
        /// 获取或设置当前活力值
        /// </summary>
        public double VEnergy { get; set; }

        /// <summary>
        /// 获取或设置最大活力值
        /// </summary>
        public double VEnergyMax { get; set; }

        /// <summary>
        /// 获取或设置属性基数
        /// 0-14对应基础属性值
        /// </summary>
        public double[] ABase { get; set; }

        /// <summary>
        /// 获取或设置装备加成总和
        /// 0-14对应基础属性值
        /// 15-19对应5大属性
        /// </summary>
        public double[] Equip { get; set; }

        /// <summary>
        /// 获取或设置加持/减持值总和
        /// 0-14对应基础属性值
        /// 15-19对应5大属性
        /// </summary>
        public double[] Buff { get; set; }

        /// <summary>
        /// 获取或设置属性系数(成长率)
        /// 0-14对应基础属性值
        /// </summary>
        public double[] Coefficient { get; set; }

        double _VPower;
        /// <summary>
        /// 获取或设置力量
        /// 影响最大负重,物理攻击力(最小 - 最大)
        /// --[相关基值属性计算公式]:
        /// 最大负重 = ABase[0] + Equip[0] + Buff[0] + VPower * Coefficient[0]
        /// 物理攻击力最小值 = ABase[1] + Equip[1] + Buff[1] + VPower * Coefficient[1]
        /// 物理攻击力最大值 = ABase[2] + Equip[2] + Buff[2] + VPower * Coefficient[2]
        /// </summary>
        public double VPower {
            get { return _VPower + Equip[16] + Buff[16]; }
            set { _VPower = value; }
        }

        double _VAgile;
        /// <summary>
        /// 获取或设置敏捷
        /// 影响命中,闪避,跑速,攻速,施法速度
        /// --[相关基值属性计算公式]:
        /// 命中 = ABase[3] + Equip[3] + Buff[3] + VAgile * Coefficient[3]
        /// 闪避 = ABase[4] + Equip[4] + Buff[4] + VAgile * Coefficient[4]
        /// 跑速 = ABase[5] - Equip[5] + Buff[5] - VAgile * Coefficient[5]
        /// 物攻速度 = ABase[6] - Equip[6] + Buff[6] - VAgile * Coefficient[6]
        /// 施法速度 = ABase[7] - Equip[7] + Buff[7] - VAgile * Coefficient[7]
        /// </summary>
        public double VAgile {
            get { return _VAgile + Equip[17] + Buff[17]; }
            set { _VAgile = value; }
        }

        double _VPhysique;
        /// <summary>
        /// 获取或设置体格
        /// 影响最大生命值,物理防御力,格档率(与暴击率相反,物理或魔法攻击伤害减半)
        /// --[相关基值属性计算公式]:
        /// 最大生命值 = ABase[8] + Equip[8] + Buff[8] + VPhysique * Coefficient[8]
        /// 物理防御力 = ABase[9] + Equip[9] + Buff[9] + VPhysique * Coefficient[9]
        /// 格档率 = ABase[10] + Equip[10] + Buff[10] + VPhysique * Coefficient[10]
        /// </summary>
        public double VPhysique {
            get { return _VPhysique + Equip[18] + Buff[18]; }
            set { _VPhysique = value; }
        }

        double _VWisdom;
        /// <summary>
        /// 获取或设置智慧
        /// 影响最大魔法值,魔法防御力,魔法攻击力(最小 - 最大)
        /// --[相关基值属性计算公式]:
        /// 最大魔法值 = ABase[11] + Equip[11] + Buff[11] + VWisdom * Coefficient[11]
        /// 魔法防御力 = ABase[12] + Equip[12] + Buff[12] + VWisdom * Coefficient[12]
        /// 魔法攻击力最小值 = ABase[13] + Equip[13] + Buff[13] + VWisdom * Coefficient[13]
        /// 魔法攻击力最大值 = ABase[14] + Equip[14] + Buff[14] + VWisdom * Coefficient[14]
        /// </summary>
        public double VWisdom {
            get { return _VWisdom + Equip[19] + Buff[19]; }
            set { _VWisdom = value; }
        }

        double _VLucky;
        /// <summary>
        /// 获取或设置幸运
        /// 影响暴击率(物理或魔法攻击加倍)及其他
        /// --[相关基值属性计算公式]:
        /// 暴击率 = ABase[15] + Equip[15] + Buff[15] + VLucky * ACoefficient[15]
        /// </summary>
        public double VLucky {
            get { return _VLucky + Equip[20] + Buff[20]; }
            set { _VLucky = value; }
        }

        #endregion

        #region 界面属性

        /// <summary>
        /// 获取或设置精灵身体蒙板是否可见
        /// </summary>
        public Visibility MaskVisibility {
            get { return Mask.Visibility; }
            set { Mask.Visibility = value; }
        }

        /// <summary>
        /// 获取或设置精灵身体蒙板颜色
        /// </summary>
        public Brush MaskColor {
            get { return Mask.Fill; }
            set { Mask.Fill = value; }
        }

        /// <summary>
        /// 设置精灵阴影
        /// </summary>
        public bool ShadowVisible {
            set { BodyShadow.BlurRadius = value ? 7 : 0; }
        }

        /// <summary>
        /// 3个身份描述与画布顶部的距离
        /// </summary>
        public double DescribtionTop {
            get { return (double)Describtion.GetValue(Canvas.TopProperty); }
            set { Describtion.SetValue(Canvas.TopProperty, value); }
        }

        /// <summary>
        /// 获取或设置精灵身体高度
        /// </summary>
        public double BodyHeight {
            get { return Body.Height; }
            set { Body.Height = value; }
        }

        /// <summary>
        /// 设置门派名颜色笔刷
        /// </summary>
        public Brush FactionBrush {
            set { Faction.Foreground = value; }
        }

        /// <summary>
        /// 设置家族名颜色笔刷
        /// </summary>
        public Brush ClanBrush {
            set { Clan.Foreground = value; }
        }

        /// <summary>
        /// 设置姓名颜色笔刷
        /// </summary>
        public Brush SNameBrush {
            set { SName.Foreground = value; }
        }

        /// <summary>
        /// 设置头顶生命值条颜色笔刷
        /// </summary>
        public Brush LifeBrush {
            set { Life.Fill = value; }
        }

        /// <summary>
        /// 获取或设置头顶生命值条当前宽度
        /// </summary>
        public double LifeWidth {
            get { return Life.Width; }
            set { if (LifeWidth != value) { Life.Width = value; } }
        }

        /// <summary>
        /// 获取或设置头顶生命值条满值宽度
        /// </summary>
        public double LifeTotalWidth {
            get { return LifePanel.Width; }
            set { LifePanel.Width = value; LifeBorder.Width = value; }
        }

        /// <summary>
        /// 获取或设置精灵图片宽
        /// </summary>
        public double Width_ {
            get { return Body.Width; }
            set { Body.Width = value; Mask.Width = value; Describtion.Width = value; }
        }

        /// <summary>
        /// 获取或设置精灵图片高
        /// </summary>
        public double Height_ {
            get { return Body.Height; }
            set { Body.Height = value; Mask.Height = value; }
        }

        /// <summary>
        /// 获取或设置精灵单位图片左上角点与精灵图片中角色脚底的X距离
        /// </summary>
        public double CenterX { get; set; }

        /// <summary>
        /// 获取或设置精灵单位图片左上角点与精灵图片中角色脚底的Y距离
        /// </summary>
        public double CenterY { get; set; }

        /// <summary>
        /// 获取或设置精灵坐标(关联属性)
        /// </summary>
        public Point Coordinate {
            get { return (Point)GetValue(CoordinateProperty); }
            set { SetValue(CoordinateProperty, value); }
        }
        public static readonly DependencyProperty CoordinateProperty = DependencyProperty.Register(
            "Coordinate",
            typeof(Point),
            typeof(QXSprite),
            new PropertyMetadata(ChangeCoordinateProperty)
        );
        private static void ChangeCoordinateProperty(DependencyObject d, DependencyPropertyChangedEventArgs e) {
            QXSprite obj = (QXSprite)d;
           
            if (obj.Visibility == Visibility.Visible) {
                Point p = (Point)e.NewValue;
                obj.SetValue(Canvas.LeftProperty, p.X - obj.CenterX);
                obj.SetValue(Canvas.TopProperty, p.Y - obj.CenterY);
                obj.SetValue(Canvas.ZIndexProperty, (int)p.Y);
            }
        }

        /// <summary>
        /// 获取或设置精灵当前朝向:0朝上4朝下,顺时针依次为0,1,2,3,4,5,6,7(关联属性)
        /// </summary>
        public double Direction {
            get { return (double)GetValue(DirectionProperty); }
            set { SetValue(DirectionProperty, value); }
        }
        public static readonly DependencyProperty DirectionProperty = DependencyProperty.Register(
            "Direction",
            typeof(double),
            typeof(QXSprite),
            null
        );

        /// <summary>
        /// 获取或设置组合与精灵身体上的部件偏移量(如装备合成及魔法特效装饰等)
        /// </summary>
        public Point ComponentsOffset { get; set; }

        #endregion

        #region 控件属性

        /// <summary>
        /// 获取或设置锁定的目标精灵对象
        /// </summary>
        public string LockObject { get; set; }

        /// <summary>
        /// 获取或设置脚底示为障碍物区域扩展宽度
        /// </summary>
        public int HoldWidth { get; set; }

        /// <summary>
        /// 获取或设置脚底示为障碍物区域扩展高度
        /// </summary>
        public int HoldHeight { get; set; }

        /// <summary>
        /// 获取或设置物理攻击范围(距离)
        /// </summary>
        public int AttackRange { get; set; }

        /// <summary>
        /// 获取或设置索敌范围(距离)
        /// </summary>
        public int SeekRange { get; set; }

        /// <summary>
        /// 获取或设置精灵图片实体部分(共4个部分x1-x2,y1-y2)
        /// </summary>
        public double[] EfficaciousSection { get; set; }

        Actions _Action;
        /// <summary>
        /// 获取或设置精灵当前动作
        /// </summary>
        public Actions Action {
            get { return _Action; }
            set { if (_Action != value) { _Action = value; ChangeAction(); } }
        }

        /// <summary>
        /// 获取或设置精灵类型
        /// </summary>
        public SpriteTypes Type { get; set; }

        /// <summary>
        /// 获取或设置精灵各动作对应的帧列范围(暂时只有5个动作)
        /// </summary>
        public int[] EachActionFrameRange { get; set; }

        /// <summary>
        /// 获取或设置精灵单张图片宽
        /// </summary>
        public int SingleWidth { get; set; }

        /// <summary>
        /// 获取或设置精灵单张图片高
        /// </summary>
        public int SingleHeight { get; set; }

        /// <summary>
        /// 获取或设置精灵移动目的地
        /// </summary>
        public Point Destination { get; set; }

        /// <summary>
        /// 获取或设置精灵的魔法攻击目标坐标
        /// </summary>
        public Point MagicTarget { get; set; }

        /// <summary>
        /// 是否启用了A*移动
        /// </summary>
        public bool UseAStarMove { get; set; }

        /// <summary>
        /// 获取或设置是否为移动后施法过程
        /// </summary>
        public bool IsMagicMove { get; set; }

        /// <summary>
        /// 获取或设置精灵当前准备或右键魔法相关参数
        /// [0],代号
        /// [1],等级
        /// </summary>
        public int[] MagicArgs { get; set; }

        /// <summary>
        /// 施法距离
        /// </summary>
        public int MagicRange { get; set; }

        /// <summary>
        /// 获取或设置精灵衣服代码
        /// </summary>
        public int EquipmentBody { get; set; }

        /// <summary>
        /// 获取或设置精灵武器代码
        /// </summary>
        public int EquipmentWeapon { get; set; }

        /// <summary>
        /// 获取或设置帧推进器
        /// </summary>
        public int FrameCounter { get; set; }

        /// <summary>
        /// 获取或设置精灵当前动作开始图片列号
        /// </summary>
        public int StartFrame { get; set; }

        /// <summary>
        /// 获取或设置精灵当前动作结束图片列号
        /// </summary>
        public int EndFrame { get; set; }

        /// <summary>
        /// 获取或设置各动作产生实际效果的针序号
        /// </summary>
        public int[] EffectiveFrame { get; set; }

        /// <summary>
        /// 获取或设置精灵生命线程的刷新率
        /// </summary>
        public TimeSpan RefreshRate {
            get { return Timer.Interval; }
            set { Timer.Interval = value; }
        }

        #endregion

        #region 方法与事件

        bool isDeath = false, hasAdditionalEffect; int deathDelay = 0;
        /// <summary>
        /// 计时器事件
        /// </summary>
        private void Timer_Tick(object sender, EventArgs e) {
            if (isDeath) {
                deathDelay += 1;
                if (deathDelay == 6) {
                    Super.RemoveObject(this, true);
                }
                return;
            }
            //动态更改精灵图片源以形成精灵连续动作
            Body.Source = EquipmentWeapon == -1
                ? Super.GetImage(string.Format(@"/Image/Role/Body/{0}/{1}-{2}.png", EquipmentBody, (int)Direction, FrameCounter))
                : Super.ComposeEquip(
                        string.Format(@"/Image/Role/Body/{0}/{1}-{2}.png", EquipmentBody, (int)Direction, FrameCounter),
                        string.Format(@"/Image/Role/Weapon/{0}/{1}-{2}.png", EquipmentWeapon, (int)Direction, FrameCounter),
                        SingleWidth,
                        SingleHeight,
                        ComponentsOffset);
            //动态更改精灵蒙板层图片源
            hasAdditionalEffect = false;
            for (int i = 0; i < AdditionalEffectTime.Count(); i++) {
                if (AdditionalEffectTime[i] > 0) {
                    MaskImage.ImageSource = Body.Source;
                    MaskVisibility = Visibility.Visible;
                    hasAdditionalEffect = true;
                    break;
                }
            }
            if (!hasAdditionalEffect) { MaskVisibility = Visibility.Collapsed; }
            if (AdditionalEffectTime[2] > 0) { return; } //假如冰冻则不执行下面动作
            //如果触动起效帧
            if (FrameCounter == EffectiveFrame[(int)Action]) {
                switch (Action) {
                    case Actions.Attack:
                        Super.DoInjure(this);
                        if (this.Name == "Leader") {
                            Super.gameAudio.Source = new Uri(@"/Audio/sword.mp3", UriKind.Relative);
                            Super.gameAudio.Play();
                        }
                        break;
                    case Actions.Magic:
                        QXMagic magic = Super.GetMagicByCode(MagicArgs[0].ToString());
                        magic.MagicOwner = this.Name;
                  
                        magic.Coordinate = this.MagicTarget;
                        double centerX = magic.CenterX;
                        int consumption = magic.Consumption;
                        //只有魔力值足够才能放魔法
                        if (VMana < consumption) {
                            Super.ShowText(this, FontWeights.Bold, FontStyles.Italic, "魔法值不足", 24, Colors.Green);
                        } else {
                            //设定所有魔法的基础参数
                            VMana -= consumption;
                         
                            //根据魔法Mode来不同对待
                            switch (magic.Mode) {
                                case 0:
                                    break;
                                case 1:
                                    //其中的this.Coordinate.Y - 40是将发射点定位到精灵手部
                                    magic.Coordinate = new Point(this.Coordinate.X, this.Coordinate.Y - 40);
                                    magic.Angle = Super.GetAngle(MagicTarget.Y - (this.Coordinate.Y - 40), MagicTarget.X - this.Coordinate.X);
                                    magic.RenderTransform = new RotateTransform() {
                                        CenterX = 0,
                                        CenterY = centerX,
                                        Angle = magic.Angle
                                    };
                                    magic.Timer.Interval = TimeSpan.FromMilliseconds(40);
                                    break;
                            }
                            magic.Timer.Start();
                            ParentCanvas.Children.Add(magic);
                        }
                        //主角则放音效
                        if (this.Name == "Leader") {
                            Super.gameAudio.Source = new Uri(@"/Audio/magic.mp3", UriKind.Relative);
                            Super.gameAudio.Play();
                        }
                        break;
                    case Actions.Death:
                        isDeath = true;
                        break;
                }
            }
            if (Action == Actions.Magic && FrameCounter == EndFrame) {
                //放完魔法停止
                IsMagicMove = false;
                Action = Actions.Stop;
            }
            FrameCounter = FrameCounter == EndFrame ? StartFrame : FrameCounter + 1;
        }

        /// <summary>
        /// 改变精灵动作状态后激发的属性
        /// </summary>
        private void ChangeAction() {
            switch (Action) {
                case Actions.Stop:
                    RefreshThread(400, 0, EachActionFrameRange[0] - 1);
                    break;
                case Actions.Run:
                    RefreshThread(VRunSpeed, EachActionFrameRange[0], EachActionFrameRange[0] + EachActionFrameRange[1] - 1);
                    break;
                case Actions.Attack:
                    RefreshThread(VAttackSpeed, EachActionFrameRange[0] + EachActionFrameRange[1], EachActionFrameRange[0] + EachActionFrameRange[1] + EachActionFrameRange[2] - 1);
                    break;
                case Actions.Magic:
                    RefreshThread(VMagicSpeed, EachActionFrameRange[0] + EachActionFrameRange[1] + EachActionFrameRange[2], EachActionFrameRange[0] + EachActionFrameRange[1] + EachActionFrameRange[2] + EachActionFrameRange[3] - 1);
                    break;
                case Actions.Death:
                    RefreshThread(300, EachActionFrameRange[0] + EachActionFrameRange[1] + EachActionFrameRange[2] + EachActionFrameRange[3], EachActionFrameRange[0] + EachActionFrameRange[1] + EachActionFrameRange[2] + EachActionFrameRange[3] + EachActionFrameRange[4] - 1);
                    break;
            }
            FrameCounter = StartFrame;
        }

        /// <summary>
        /// 刷新精灵
        /// </summary>
        /// <param name="timeSpan">动作图片切换间隔</param>
        /// <param name="startFrame">动作在合成大图中的开始列</param>
        /// <param name="endFrame">动作在合成大图中的结束列</param>
        private void RefreshThread(double timeSpan, int startFrame, int endFrame) {
            RefreshRate = TimeSpan.FromMilliseconds(timeSpan);
            StartFrame = startFrame;
            EndFrame = endFrame;
        }

        //必须注册此事件,否则会造成系统崩溃,由蒙板图片源引发
        private void MaskImage_ImageFailed(object sender, ExceptionRoutedEventArgs e) {
            sender = null;
        }

        #endregion

    }
}
